﻿using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;

namespace SHomeWorkshop.LunarPresentation.Widegets
{
    public class BracketPanel : Canvas
    {
        public BracketPanel()
        {
            this.Width = 24;
            this.Background = Brushes.Transparent;
            this.SizeChanged += new SizeChangedEventHandler(BracketPanel_SizeChanged);
        }

        private Path myPath;

        public enum BracketLocation { Top, Bottom, Left, Right }

        /// <summary>
        /// 括弧位置，默认为左括弧（开口向右）。
        /// </summary>
        private BracketLocation location = BracketLocation.Left;

        public BracketLocation Location
        {
            get { return location; }
            set
            {
                location = value;
                switch (location)
                {
                    case BracketLocation.Left:
                    case BracketLocation.Right:
                        {
                            Width = 24; Height = double.NaN; break;
                        }
                    case BracketLocation.Top:
                    case BracketLocation.Bottom:
                        {
                            Height = 24; Width = double.NaN; break;
                        }
                }
            }
        }

        private Brush foreground=Brushes.White;

        public Brush Foreground
        {
            get { return foreground; }
            set
            {
                foreground = value;
                RefreshBracketPath();
            }
        }

        public void RefreshBracketPath()
        {
            this.Children.Clear();

            myPath = new Path();
            //myPath.MouseDown += new System.Windows.Input.MouseButtonEventHandler(myPath_MouseDown);
            myPath.StrokeStartLineCap = PenLineCap.Round;
            myPath.StrokeEndLineCap = PenLineCap.Round;
            myPath.Stroke = foreground;
            myPath.StrokeThickness = 2;
            myPath.StrokeLineJoin = PenLineJoin.Round;
            RenderOptions.SetClearTypeHint(myPath, ClearTypeHint.Enabled);

            StreamGeometry geometry = new StreamGeometry();
            //geometry.FillRule = FillRule.EvenOdd;

            double halfOfWidth = this.ActualWidth / 2;
            double halfOfHeight = this.ActualHeight / 2;
            double quarterOfWidth = this.ActualWidth / 4;
            double quarterOfHeight = this.ActualHeight / 4;

            switch (location)
            {
                case BracketLocation.Left:
                    {
                        DrawLeftBracket(geometry, halfOfWidth, halfOfHeight, quarterOfWidth);
                        break;
                    }
                case BracketLocation.Right:
                    {
                        DrawRightBracket(geometry, halfOfWidth, halfOfHeight, quarterOfWidth);
                        break;
                    }
                case BracketLocation.Top:
                    {
                        DrawTopBracket(geometry, halfOfWidth, halfOfHeight, quarterOfHeight);
                        break;
                    }
                case BracketLocation.Bottom:
                    {
                        DrawBottomBracket(geometry, halfOfWidth, halfOfHeight, quarterOfHeight);
                        break;
                    }
            }

            myPath.Data = geometry;

            this.Children.Add(myPath);
        }

        void BracketPanel_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            RefreshBracketPath();
        }

        //void myPath_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
        //{
        //    this.OnMouseDown(e);
        //}

        private void DrawLeftBracket(StreamGeometry geometry, double halfOfWidth, double halfOfHeight, double quarterOfWidth)
        {
            Point apt = new Point(quarterOfWidth * 3, quarterOfWidth);
            Point bpt = new Point(halfOfWidth, quarterOfWidth);
            Point cpt = new Point(halfOfWidth, halfOfWidth /*+ quarterOfWidth*/);
            Point dpt = new Point(halfOfWidth, halfOfHeight - quarterOfWidth/* * 2*/);

            Point ept = new Point(halfOfWidth, halfOfHeight);
            Point fpt = new Point(quarterOfWidth, halfOfHeight);
            Point gpt = new Point(halfOfWidth, halfOfHeight + quarterOfWidth/* * 2*/);
            Point hpt = new Point(halfOfWidth, this.ActualHeight - halfOfWidth /*- quarterOfWidth*/);

            Point ipt = new Point(halfOfWidth, this.ActualHeight - quarterOfWidth);
            Point jpt = new Point(quarterOfWidth * 3, this.ActualHeight - quarterOfWidth);

            using (StreamGeometryContext ctx = geometry.Open())
            {
                ctx.BeginFigure(apt, false /* is filled */, false /* is closed */);

                if (cpt.Y > dpt.Y || gpt.Y > hpt.Y)
                {
                    Point newB = new Point(bpt.X - quarterOfWidth, bpt.Y);
                    Point newE = new Point(ept.X + quarterOfWidth, ept.Y);
                    Point newI = new Point(ipt.X - quarterOfWidth, ipt.Y);
                    ctx.BezierTo(newB, newE, fpt, true, true);
                    ctx.BezierTo(newE, newI, jpt, true, true);
                }
                else
                {
                    ctx.QuadraticBezierTo(bpt, cpt, true, true);
                    ctx.LineTo(dpt, true, true);
                    ctx.QuadraticBezierTo(ept, fpt, true, true);
                    ctx.QuadraticBezierTo(ept, gpt, true, true);
                    ctx.LineTo(hpt, true, true);
                    ctx.QuadraticBezierTo(ipt, jpt, true, true);
                }
            }
        }

        private void DrawRightBracket(StreamGeometry geometry, double halfOfWidth, double halfOfHeight, double quarterOfWidth)
        {
            Point apt = new Point(quarterOfWidth, quarterOfWidth);
            Point bpt = new Point(halfOfWidth, quarterOfWidth);
            Point cpt = new Point(halfOfWidth, halfOfWidth /*+ quarterOfWidth*/);
            Point dpt = new Point(halfOfWidth, halfOfHeight - quarterOfWidth/* * 2*/);

            Point ept = new Point(halfOfWidth, halfOfHeight);
            Point fpt = new Point(quarterOfWidth * 3, halfOfHeight);
            Point gpt = new Point(halfOfWidth, halfOfHeight + quarterOfWidth/* * 2*/);
            Point hpt = new Point(halfOfWidth, this.ActualHeight - halfOfWidth /*- quarterOfWidth*/);

            Point ipt = new Point(halfOfWidth, this.ActualHeight - quarterOfWidth);
            Point jpt = new Point(quarterOfWidth, this.ActualHeight - quarterOfWidth);

            using (StreamGeometryContext ctx = geometry.Open())
            {
                ctx.BeginFigure(apt, false /* is filled */, false /* is closed */);

                if (cpt.Y > dpt.Y || gpt.Y > hpt.Y)
                {
                    Point newB = new Point(bpt.X + quarterOfWidth, bpt.Y);
                    Point newE = new Point(ept.X - quarterOfWidth, ept.Y);
                    Point newI = new Point(ipt.X + quarterOfWidth, ipt.Y);
                    ctx.BezierTo(newB, newE, fpt, true, true);
                    ctx.BezierTo(newE, newI, jpt, true, true);
                }
                else
                {
                    ctx.QuadraticBezierTo(bpt, cpt, true, true);
                    ctx.LineTo(dpt, true, true);
                    ctx.QuadraticBezierTo(ept, fpt, true, true);
                    ctx.QuadraticBezierTo(ept, gpt, true, true);
                    ctx.LineTo(hpt, true, true);
                    ctx.QuadraticBezierTo(ipt, jpt, true, true);
                }
            }
        }

        private void DrawTopBracket(StreamGeometry geometry, double halfOfWidth, double halfOfHeight, double quarterOfHeight)
        {
            Point apt = new Point(quarterOfHeight, quarterOfHeight * 3);
            Point bpt = new Point(quarterOfHeight, halfOfHeight);
            Point cpt = new Point(halfOfHeight, halfOfHeight);
            Point dpt = new Point(halfOfWidth - quarterOfHeight, halfOfHeight);

            Point ept = new Point(halfOfWidth, halfOfHeight);
            Point fpt = new Point(halfOfWidth, quarterOfHeight);
            Point gpt = new Point(halfOfWidth + quarterOfHeight, halfOfHeight);
            Point hpt = new Point(this.ActualWidth - halfOfHeight, halfOfHeight);

            Point ipt = new Point(this.ActualWidth - quarterOfHeight, halfOfHeight);
            Point jpt = new Point(this.ActualWidth - quarterOfHeight, quarterOfHeight * 3);

            using (StreamGeometryContext ctx = geometry.Open())
            {
                ctx.BeginFigure(apt, false /* is filled */, false /* is closed */);

                if (cpt.X > dpt.X || gpt.X > hpt.X)
                {
                    Point newB = new Point(bpt.X, bpt.Y - quarterOfHeight);
                    Point newE = new Point(ept.X, ept.Y + quarterOfHeight);
                    Point newI = new Point(ipt.X, ipt.Y - quarterOfHeight);
                    ctx.BezierTo(newB, newE, fpt, true, true);
                    ctx.BezierTo(newE, newI, jpt, true, true);
                }
                else
                {
                    ctx.QuadraticBezierTo(bpt, cpt, true, true);
                    ctx.LineTo(dpt, true, true);
                    ctx.QuadraticBezierTo(ept, fpt, true, true);
                    ctx.QuadraticBezierTo(ept, gpt, true, true);
                    ctx.LineTo(hpt, true, true);
                    ctx.QuadraticBezierTo(ipt, jpt, true, true);
                }
            }
        }

        private void DrawBottomBracket(StreamGeometry geometry, double halfOfWidth, double halfOfHeight, double quarterOfHeight)
        {
            Point apt = new Point(quarterOfHeight, quarterOfHeight);
            Point bpt = new Point(quarterOfHeight, halfOfHeight);
            Point cpt = new Point(halfOfHeight, halfOfHeight);
            Point dpt = new Point(halfOfWidth - quarterOfHeight, halfOfHeight);

            Point ept = new Point(halfOfWidth, halfOfHeight);//中心点

            Point fpt = new Point(halfOfWidth, quarterOfHeight * 3);
            Point gpt = new Point(halfOfWidth + quarterOfHeight, halfOfHeight);
            Point hpt = new Point(this.ActualWidth - halfOfHeight, halfOfHeight);

            Point ipt = new Point(this.ActualWidth - quarterOfHeight, halfOfHeight);
            Point jpt = new Point(this.ActualWidth - quarterOfHeight, quarterOfHeight);

            using (StreamGeometryContext ctx = geometry.Open())
            {
                ctx.BeginFigure(apt, false /* is filled */, false /* is closed */);

                if (cpt.X > dpt.X || gpt.X > hpt.X)
                {
                    Point newB = new Point(bpt.X, bpt.Y + quarterOfHeight);
                    Point newE = new Point(ept.X, ept.Y - quarterOfHeight);
                    Point newI = new Point(ipt.X, ipt.Y + quarterOfHeight);
                    ctx.BezierTo(newB, newE, fpt, true, true);
                    ctx.BezierTo(newE, newI, jpt, true, true);
                }
                else
                {
                    ctx.QuadraticBezierTo(bpt, cpt, true, true);
                    ctx.LineTo(dpt, true, true);
                    ctx.QuadraticBezierTo(ept, fpt, true, true);
                    ctx.QuadraticBezierTo(ept, gpt, true, true);
                    ctx.LineTo(hpt, true, true);
                    ctx.QuadraticBezierTo(ipt, jpt, true, true);
                }
            }
        }
    }
}
